/*******************************************************************************
 * Copyright (c) 2003 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     Erich Gamma (erich_gamma@ch.ibm.com) and
 * 	   Kent Beck (kent@threeriversinstitute.org)
 *******************************************************************************/
package hku.cs.lunuo.run;

import hku.cs.lunuo.LunuoLog;
import hku.cs.lunuo.LunuoPlugin;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.core.Launch;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.launching.IVMInstall;
import org.eclipse.jdt.launching.IVMRunner;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jdt.launching.VMRunnerConfiguration;

public class Runner {
//	static final String MAIN_CLASS= "hku.cfg.Class";
	static final String MAIN_CLASS="hku.cs.lunuo.vmrun.SocketRunner";
	private int port;
	private IJavaProject project;
	private BufferedReader reader;

	public Runner() {
	}

	
	public void run(List<IJavaElement> jes, IProgressMonitor monitor) throws CoreException {
		if(jes.size() == 0)
			return;
		
		if (monitor == null) {
			monitor = new NullProgressMonitor();
		}
		
		monitor.beginTask("", 5); //$NON-NLS-1$
		// check for cancellation
		if (monitor.isCanceled()) {
			return;
		}
		
		
		List<String> filters;
		IResource resource = (IResource) project.getAdapter(
				IResource.class);
		try {
			String value = resource
					.getPersistentProperty(LunuoPlugin.FILTER_PROPERTY);
			if (value == null) {
				filters = Arrays.asList(new String[0]);
			}else
				filters = Arrays.asList(value.split(";"));
		} catch (CoreException e) {
			LunuoLog.logError(e);
			filters = Arrays.asList(new String[0]);
		}
		
		monitor.subTask("");
		
		IVMInstall vmInstall= getVMInstall();
		if (vmInstall == null)
			return;
			
		IVMRunner vmRunner= vmInstall.getVMRunner(ILaunchManager.RUN_MODE);
		if (vmRunner == null)
			return;
			
		String[] classPath= computeClasspath();
		VMRunnerConfiguration vmConfig= new VMRunnerConfiguration(MAIN_CLASS, classPath);
		
		if (monitor.isCanceled()) {
			return;
		}	
		
		List<String> sourceDirs = new ArrayList<String>();
		IClasspathEntry xx[]= project.getRawClasspath();
		
		for(int i=0; i<xx.length; i++)
			if (xx[i].getEntryKind() == IClasspathEntry.CPE_SOURCE){
				sourceDirs.add(xx[i].getPath().toString());
			}
		
		StringBuffer runClasses = new StringBuffer();
		for(IJavaElement je : jes){
			String stre = je.getPath().toString();
			for(String osd: sourceDirs){
				if(stre.startsWith(osd)){
					stre = stre.substring(osd.length()+1, stre.length());
					break;
				}			
			}
			stre = stre.replace('/', '.');
			stre = stre.substring(0, stre.lastIndexOf('.'));
			
			
			
			if(stre.lastIndexOf('.')!=-1){
				if(!filters.contains(stre.substring(0, stre.lastIndexOf('.')))){
					runClasses.append(stre);
					runClasses.append(";");
				}
			}else{
				if(!filters.contains("(default package)")){
					runClasses.append(stre);
					runClasses.append(";");
				}
			}			
		}
		
		String output = LunuoPlugin.METADIR.append(project.getOutputLocation()).toOSString();
//		String[] args = new String[]{Integer.toString(SocketUtil.findFreePort()), stre};
		String[] args = new String[]{
			output, runClasses.toString()};
		
		if (monitor.isCanceled()) {
			return;
		}	
		
		monitor.worked(1);
		
		monitor.subTask(""); 
		// set the default source locator if required
		monitor.worked(1);
		
		vmConfig.setProgramArguments(args);
		ILaunch launch= new Launch(null, ILaunchManager.RUN_MODE, null);
		
		vmRunner.run(vmConfig, launch, monitor);
//		DebugPlugin.getDefault().getLaunchManager().addLaunch(launch);
		
		if (monitor.isCanceled()) {
			return;
		}
//		connect();
	}
	
	
	
	
	private String[] computeClasspath() throws CoreException {
		String[] defaultPath= JavaRuntime.computeDefaultRuntimeClassPath(project);
		String[] classPath = null;
		
		LunuoPlugin plugin= LunuoPlugin.getDefault();
		try {
			String path = FileLocator.getBundleFile(plugin.getBundle()).getAbsolutePath()+File.separator;
			String lunuoPath = path;

			path = path + "lib"+File.separator;
			String[] libs = new File(path).list();
			for(int i=0; i<libs.length; i++)
				libs[i]=path + libs[i];
			
			classPath = new String[defaultPath.length + 2 + libs.length];			
			
			System.arraycopy(defaultPath, 0, classPath, 0, defaultPath.length);
			classPath[defaultPath.length] = lunuoPath +"bin\\";
			System.arraycopy(libs, 0, classPath, defaultPath.length+1, libs.length);
			classPath[classPath.length-1] = lunuoPath +"src\\";
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
		return classPath;
	}
	
	private void connect() {
		try {
			ServerSocket server;
			server= new ServerSocket(port);
			try {
				Socket socket= server.accept();
				try {
					readMessage(socket);
				} finally {
					socket.close();
				}
			} finally {
				server.close();
			}
		} catch (IOException e) {
			//TODO unhandled exception
			e.printStackTrace();
		}
	}
	
	private void readMessage(Socket socket) throws IOException {
		reader= new BufferedReader(new InputStreamReader(socket.getInputStream()));
		try {
			String line= null;
			while ((line= reader.readLine()) != null) {
				parseMessage(line);
			}
		} finally {
			reader.close();
		}
	}
	
	private void parseMessage(String line) {
		LunuoPlugin plugin= LunuoPlugin.getDefault();
		
	}
	private IVMInstall getVMInstall() throws CoreException {
		IVMInstall vmInstall= JavaRuntime.getVMInstall(project);
		if (vmInstall == null)
			vmInstall= JavaRuntime.getDefaultVMInstall();
		return vmInstall;
	}
}